/**
 * 
 */
package models;

import java.util.*;

import models.Table;
import play.*;
import play.libs.*;
import play.libs.F.*;
import play.mvc.*;
import views.html.*;

import com.fasterxml.jackson.databind.JsonNode; 
import com.fasterxml.jackson.databind.node.*;

import controllers.Clients;
import controllers.Game;


/**
 * @author Administrator

 *
 */

@SuppressWarnings("unused")
public class Client {
	
	private String User;
	private int ID;
	private WebSocket.In<JsonNode> In = null;
	private WebSocket.Out<JsonNode> Out = null;
	
	public Client( String User, int ID, WebSocket.In<JsonNode> In, WebSocket.Out<JsonNode> Out)  {
		
		this.User = User;
		this.ID = ID;
		this.In = In;
		this.Out = Out;
	}
	
	public Client( String User, int ID )  {
		
		this.User = User;
		this.ID = ID;
	}
	
	public String getUser() {
		return User;
	}
	
	public int getID() {
		return ID;
	}
	
	public void setUser(String User) {
		this.User = User;
	}
	
	public void setID(int ID) {
		this.ID = ID;
	}
	
	public WebSocket.In<JsonNode> getIn() {
		return In;
	}
	
	public WebSocket.Out<JsonNode> getOut() {
		return Out;
	}
	
	public void setIn(WebSocket.In<JsonNode> In) {
		this.In = In;
		UpdateInSocket();
	}
	
	public void setOut(WebSocket.Out<JsonNode> Out) {
		this.Out = Out;
	}
	
	public void ReceiveMessage(JsonNode e) {
		
		// if received messages are settings for new game
		if ( e.has("settings_players") ) {
			Game.HumansNumber = e.get("settings_players").asInt();
		}
		
		if ( e.has("settings_bots") ) {
			Game.BotsNumber = e.get("settings_bots").asInt();
		}
		
		if ( e.has("settings_tokens") ) {
			Game.StartToken = e.get("settings_tokens").asInt();
		}
		
		if ( e.has("settings_ante") ) {
			Game.Ante = e.get("settings_ante").asInt();
		}
		
		// if received message is an action
		if ( e.has("action") ) {
			
			System.out.println("         "+this.getUser()+" received message: "+e);
			
			switch ( e.get("action").asText() ) {
			
				case "new_game":
					//System.out.println(e);
					try {
						if ( Game.CheckSettings() )
							Game.GameCreate(this);
					}
					catch (Exception ex) {
						// fail
						ex.printStackTrace();
						Clients.SendMessageTo(this, "message", ex.getMessage());
					}
				break;
				
				case "join_game":
					//System.out.println(e);
					try {
						Game.GameJoin(this);
					}
					catch (Exception ex) {
						// fail
						ex.printStackTrace();
						Clients.SendMessageTo(this, "message", ex.getMessage());
					}
				break;
				
				case "replace":
					//System.out.println(e);
					int ReplaceCards[] = new int[5];
					
					ReplaceCards[0] = e.get("card0").asInt();
					ReplaceCards[1] = e.get("card1").asInt();
					ReplaceCards[2] = e.get("card2").asInt();
					ReplaceCards[3] = e.get("card3").asInt();
					ReplaceCards[4] = e.get("card4").asInt();
					
					//System.out.println(e);
					
					try {
						Game.ReplaceCards(this, ReplaceCards);
					}
					catch (Exception ex) {
						// fail
						ex.printStackTrace();
						Clients.SendMessageTo(this, "message", ex.getMessage());
					}
					
				break;
				
				case "confirm":
					
					try {
						Game.Confirm(this);
					}
					catch (Exception ex) {
						// fail
						ex.printStackTrace();
						Clients.SendMessageTo(this, "message", ex.getMessage());
					}
					
				break;
				
				case "fold":
					
					try {
						Game.Fold(this);
					}
					catch (Exception ex) {
						// fail
						ex.printStackTrace();
						Clients.SendMessageTo(this, "message", ex.getMessage());
					}
					
				break;
					
				case "check":
					
					try {
						Game.Check(this);
					}
					catch (Exception ex) {
						// fail
						ex.printStackTrace();
						Clients.SendMessageTo(this, "message", ex.getMessage());
					}
					
				break;
				
				case "call":
					
					try {
						Game.Call(this);
					}
					catch (Exception ex) {
						// fail
						ex.printStackTrace();
						Clients.SendMessageTo(this, "message", ex.getMessage());
					}
					
				break;
					
				case "allin":
					
					try {
						Game.Allin(this);
					}
					catch (Exception ex) {
						// fail
						ex.printStackTrace();
						Clients.SendMessageTo(this, "message", ex.getMessage());
					}
					
				break;
				
				case "bet":
					
					int BetValue = e.get("amount").asInt();
					
					try {
						Game.Bet(this, BetValue);
					}
					catch (Exception ex) {
						// fail
						ex.printStackTrace();
						Clients.SendMessageTo(this, "message", ex.getMessage());
					}
					
				break;
					
				case "raise":
					
					int RaiseValue = e.get("amount").asInt();
					
					try {
						//System.out.println(RaiseValue);
						Game.Raise(this, RaiseValue);
					}
					catch (Exception ex) {
						// fail
						ex.printStackTrace();
						Clients.SendMessageTo(this, "message", ex.getMessage());
					}
					
				break;
				
				
				default:
					// ...
				break;
			}
		}
	}
	
	private void UpdateInSocket() {
		
		In.onMessage(new Callback<JsonNode>()
		{
			@Override
			public void invoke(JsonNode event)
			{
				try
				{
					//System.out.println(event);
					
					ReceiveMessage(event);
				}
				catch (Exception e)
				{
					//System.out.println(event);
		    		e.printStackTrace();
				}
		                
			}
		});

		In.onClose(new Callback0()
		{
			@Override
		    public void invoke()
		    {	
				System.out.println("WebSocket Disconnect - "+User);
		    	Clients.ClientDisconnect(ID);
		    	Clients.SendMessageToAll("message",User+" disconnected!");
		    }
		});
	}

}
